package controllers.customer;

import java.util.Collection;
import java.util.Date;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import services.AuctionService;
import services.BidService;
import controllers.AbstractController;
import domain.Auction;
import domain.Bid;
import forms.BidForm;

@Controller
@RequestMapping("/bid/customer")
public class BidCustomerController extends AbstractController {

	// Services
	@Autowired
	private BidService bidService;
	@Autowired
	private AuctionService auctionService;

	// Constructor
	public BidCustomerController() {
		super();
	}

	// Listing methods
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public ModelAndView list(@RequestParam int auctionId) {
		ModelAndView result;
		Collection<Bid> bids;
		Boolean isWinner;
		Integer idWinningBid;
		Auction auction;
		Boolean finishedAuction;

		idWinningBid = null;
		auction = auctionService.findOne(auctionId);
		finishedAuction = auction.getFinishMoment().before(new Date());

		isWinner = auction.getWinningBid() != null;
		if (isWinner) {
			idWinningBid = auction.getWinningBid().getId();
		}

		bids = bidService.findBidsByAuctionId(auctionId);

		result = new ModelAndView("bid/list");
		result.addObject("requestURI", "bid/customer/list.do");
		result.addObject("bids", bids);
		result.addObject("isWinner", isWinner);
		result.addObject("idWinningBid", idWinningBid);
		result.addObject("finishedAuction", finishedAuction);
		result.addObject("backURI", "/welcome/index.do");
		return result;
	}

	// Creation
	@RequestMapping(value = "/create", method = RequestMethod.GET)
	public ModelAndView create(@RequestParam int auctionId) {
		ModelAndView result;
		BidForm bidForm;
		Auction auction;
		Boolean isNew;

		auction = auctionService.findOne(auctionId);
		bidForm = bidService.createForm(auction);
		isNew = true;

		result = new ModelAndView("bid/create");
		result.addObject("bidForm", bidForm);
		result.addObject("auctionId", auctionId);
		result.addObject("requestURI", "bid/customer/edit.do");
		result.addObject("isNew", isNew);

		return result;

	}

	// Edition
	@RequestMapping(value = "/edit", method = RequestMethod.GET)
	public ModelAndView edit(@RequestParam int bidId) {
		ModelAndView result;
		BidForm bidForm;
		Bid bid;
		Boolean isNew;
		isNew = bidId == 0;
		bid = bidService.findOne(bidId);
		bidForm = bidService.bidToForm(bid);

		result = createEditModelAndView(bidForm);

		result.addObject("isNew", isNew);
		result.addObject("bidForm", bidForm);
		result.addObject("bidId", bidId);

		return result;

	}

	@RequestMapping(value = "/edit", method = RequestMethod.POST, params = "save")
	public ModelAndView save(@Valid BidForm bidForm, BindingResult binding) {
		ModelAndView result;
		Bid bid;
		Boolean isNew;
		int bidId;
		bidId = bidForm.getBidId();

		if (binding.hasErrors()) {
			result = createEditModelAndView(bidForm);
		} else {
			try {
				bid = bidService.reconstruct(bidForm);
				bidService.save(bid);
				result = new ModelAndView("redirect:../../");
			} catch (Throwable oops) {
				String currencyBid;
				String currencyAuction;
				currencyBid = bidForm.getAmount().getCurrency();
				currencyAuction = bidForm.getAuction().getStartingPrice()
						.getCurrency();

				if (!currencyAuction.equals(currencyBid)) {
					result = createEditModelAndView(bidForm,
							"bid.commit.error.currency");
					
				} else {
					result = createEditModelAndView(bidForm, "bid.commit.error");
				}
			}
		}
		if (bidForm.getBidId() == 0) {
			isNew = true;
		} else {
			isNew = false;
		}
		result.addObject("isNew", isNew);
		result.addObject("bidId", bidId);
		return result;

	}

	@RequestMapping(value = "/winner", method = RequestMethod.GET)
	public ModelAndView save(@RequestParam int bidId) {
		ModelAndView result;
		Auction auction;
		Bid bid;
		Collection<Bid> bids;
		Boolean isWinner;
		Integer idWinningBid;
		Boolean finishedAuction;

		bid = bidService.findOne(bidId);
		bidService.makeWinnerBid(bid);

		auction = bid.getAuction();

		idWinningBid = null;
		finishedAuction = auction.getFinishMoment().before(new Date());

		isWinner = auction.getWinningBid() != null;
		if (isWinner) {
			idWinningBid = auction.getWinningBid().getId();
		}

		bids = bidService.findBidsByAuctionId(auction.getId());

		result = new ModelAndView("bid/list");
		result.addObject("requestURI", "bid/customer/list.do");
		result.addObject("bids", bids);
		result.addObject("bidId", bidId);
		result.addObject("isWinner", isWinner);
		result.addObject("idWinningBid", idWinningBid);
		result.addObject("finishedAuction", finishedAuction);
		result.addObject("backURI", "/auction/customer/myAuctions.do");
		return result;
	}

	@RequestMapping(value = "/edit", method = RequestMethod.POST, params = "delete")
	public ModelAndView delete(BidForm bidForm, BindingResult binding) {
		ModelAndView result;
		int auctionId;
		Boolean isNew;
		int bidId;
		Bid bid;

		isNew = false;
		auctionId = bidForm.getAuction().getId();
		bidId = bidForm.getBidId();
		bid = bidService.findOne(bidId);

		try {
			bidService.delete(bid);
			result = new ModelAndView("auction/activeList");
		} catch (Throwable oops) {
			result = createEditModelAndView(bidForm, "bid.commit.error");
		}

		result.addObject("isNew", isNew);
		result.addObject("auctionId", auctionId);

		return result;

	}

	// Ancillary methods
	protected ModelAndView createEditModelAndView(BidForm bidForm) {
		ModelAndView result;
		result = createEditModelAndView(bidForm, null);
		return result;

	}

	protected ModelAndView createEditModelAndView(BidForm bidForm,
			String message) {
		ModelAndView result;

		result = new ModelAndView("bid/edit");
		result.addObject("bidForm", bidForm);
		result.addObject("message", message);

		return result;

	}
}
